<html>
 <head>
  <meta charset="UTF-8">
 </head>
 <body>
  <h1 data-lake-id="myNnh" id="myNnh"><span data-lake-id="u86f608cf" id="u86f608cf">典型回答</span></h1>
  <p data-lake-id="uf697cfbf" id="uf697cfbf"><br></p>
  <p data-lake-id="u44452ce1" id="u44452ce1"><span data-lake-id="uca5e8e89" id="uca5e8e89">在 Redis 中，他的hash表结构随着数据量的增大可能会导致扩容，通常是将数组大小扩大为原来的两倍，而在扩容过程中，因为容量变化了，所以元素在新的hash表中所处的位置也会随之变化，这个变化过程就是通过rehash实现的。</span></p>
  <p data-lake-id="u07707ece" id="u07707ece"><span data-lake-id="u8102d58b" id="u8102d58b">​</span><br></p>
  <p data-lake-id="u9f858b90" id="u9f858b90"><span data-lake-id="u75a38226" id="u75a38226">可以参考下hashmap的rehash过程：</span></p>
  <p data-lake-id="ucf79b243" id="ucf79b243"><span data-lake-id="u78fe2c7d" id="u78fe2c7d">​</span><br></p>
  <p data-lake-id="u758be639" id="u758be639"><span data-lake-id="u4528237d" id="u4528237d">而随着Redis的hash表越来越大，rehash的成本也会越来越高。Redis中实现了一种渐进式rehash的方案，他可以在哈希表rehash操作时，分多个步骤逐渐完成的方式，这样不会因为要一次性把所有元素都完成迁移而导致IO升高，线程阻塞。这个特性使得Redis可以在继续提供读写服务的同时，逐步迁移数据到新的哈希表，而不会对性能造成明显的影响。</span></p>
  <p data-lake-id="ue4acdb2a" id="ue4acdb2a"><span data-lake-id="ud284bcab" id="ud284bcab">​</span><br></p>
  <p data-lake-id="u797d1b43" id="u797d1b43"><span data-lake-id="ua486932b" id="ua486932b">在 Redis 中，他的hash结构其实底层是使用了两个全局哈希表的。我们把他们称之为哈希表 1 和哈希表 2。并且会维护一个rehashindex ，初始值为-1，来记录当前rehash的下标位置。</span></p>
  <p data-lake-id="u377a512d" id="u377a512d"><br></p>
  <p data-lake-id="uac118919" id="uac118919"><span data-lake-id="u9e663f68" id="u9e663f68">当我们开始向hash表中插入数据时，只使用哈希表 1，不断向其中添加数据。</span></p>
  <p data-lake-id="u068e19e7" id="u068e19e7"><span data-lake-id="u7a6faea3" id="u7a6faea3">​</span><br></p>
  <p data-lake-id="u01fddcb4" id="u01fddcb4"><img src="https://cdn.nlark.com/yuque/0/2023/png/5378072/1692419575799-517aced7-3c0b-480a-be5e-447a50ca375d.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_39%2Ctext_SmF2YSA4IEd1IFA%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10"></p>
  <p data-lake-id="ue749299b" id="ue749299b"><span data-lake-id="u55ba0623" id="u55ba0623">​</span><br></p>
  <p data-lake-id="ue66e8c09" id="ue66e8c09"><span data-lake-id="uf8a5b667" id="uf8a5b667">而随着数据逐渐增多，当元素个数和hash表中的数组长度一致时，就会触发rehash动作，这时候，会把哈希表2的容量扩大一倍。然后就开始进入rehash流程。</span></p>
  <p data-lake-id="u3771184e" id="u3771184e"><br></p>
  <p data-lake-id="ue65793e0" id="ue65793e0"><img src="https://cdn.nlark.com/yuque/0/2023/png/5378072/1692419598612-bd29a7c5-0da4-48f4-b324-8cf56f7a91b6.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_38%2Ctext_SmF2YSA4IEd1IFA%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10"></p>
  <p data-lake-id="u135d32b8" id="u135d32b8"><br></p>
  <p data-lake-id="u71656fbc" id="u71656fbc"><br></p>
  <p data-lake-id="u9d35c216" id="u9d35c216"><span data-lake-id="uec5db849" id="uec5db849">在进入rehash过程中，不会立刻把哈希表1中的数据全部rehash到哈希表2中，而是在后续有新的增删改查操作时，会从头开始进行rehash动作。</span></p>
  <p data-lake-id="u7ba9d590" id="u7ba9d590"><span data-lake-id="u69c52948" id="u69c52948">​</span><br></p>
  <p data-lake-id="ue44fbb98" id="ue44fbb98"><span data-lake-id="u145d8b1b" id="u145d8b1b">假如，我们现在要新增一个元素：</span></p>
  <p data-lake-id="ud9be064f" id="ud9be064f"><span data-lake-id="ud41a0680" id="ud41a0680">​</span><br></p>
  <p data-lake-id="u2c646394" id="u2c646394"><img src="https://cdn.nlark.com/yuque/0/2023/png/5378072/1692419675045-d8066838-5c20-4d5b-b92a-d22a5e074e3b.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_45%2Ctext_SmF2YSA4IEd1IFA%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10"></p>
  <p data-lake-id="u19c07168" id="u19c07168"><span data-lake-id="u8b33a101" id="u8b33a101">​</span><br></p>
  <p data-lake-id="u33353316" id="u33353316"><span data-lake-id="ue4d5e99b" id="ue4d5e99b">那么就会从当前的hashindex开始，把这个哈希表1的hashindex这个位置的桶中的数据全部rehash到哈希表2中，然后rehashindex +1 。</span></p>
  <p data-lake-id="ud6d2cb94" id="ud6d2cb94"><span data-lake-id="u63dc5201" id="u63dc5201">​</span><br></p>
  <p data-lake-id="ua12f07b1" id="ua12f07b1"><span data-lake-id="u90b1f6d2" id="u90b1f6d2">然后再在哈希表2中进行添加操作：</span></p>
  <p data-lake-id="uc2bc44d8" id="uc2bc44d8"><span data-lake-id="u0c70cb1a" id="u0c70cb1a">​</span><br></p>
  <p data-lake-id="u8bd9669b" id="u8bd9669b"><img src="https://cdn.nlark.com/yuque/0/2023/png/5378072/1692419800439-5a62ebb9-35f6-4814-bce1-98de88fb8a20.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_23%2Ctext_SmF2YSA4IEd1IFA%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10"></p>
  <p data-lake-id="uc3503561" id="uc3503561"><br></p>
  <p data-lake-id="ue5e3b4ab" id="ue5e3b4ab"><span data-lake-id="ue61bc15b" id="ue61bc15b">在后续的其他操作中也一样，会沿着hashindex一直往后开始进行逐个桶的rehash，一直到哈希表1中的元素全部完成rehash。</span></p>
  <p data-lake-id="u1609f92b" id="u1609f92b"><span data-lake-id="ub4aeab83" id="ub4aeab83">​</span><br></p>
  <p data-lake-id="ub64a0f5d" id="ub64a0f5d"><span data-lake-id="u395cbb68" id="u395cbb68">然后再把哈希表1和哈希表2的指针互换一下（后续会再把哈希表2给直接置为NULL），后续的增删改查继续在新的哈希表1中操作，直到下一次rehash开始。</span></p>
  <p data-lake-id="uc5370cbb" id="uc5370cbb"><span data-lake-id="u58b7e2bf" id="u58b7e2bf">​</span><br></p>
  <p data-lake-id="uf396450c" id="uf396450c"><span data-lake-id="u7f2bcdc1" id="u7f2bcdc1">​</span><br></p>
  <h1 data-lake-id="eCgTy" id="eCgTy"><span data-lake-id="u6d628994" id="u6d628994">扩展知识</span></h1>
  <p data-lake-id="ub84eba97" id="ub84eba97"><br></p>
  <h2 data-lake-id="qecAX" id="qecAX"><span data-lake-id="u4012d556" id="u4012d556">查询怎么办</span></h2>
  <p data-lake-id="u76e3855d" id="u76e3855d"><br></p>
  <p data-lake-id="u93aa4994" id="u93aa4994"><span data-lake-id="u5e610084" id="u5e610084">在Rehash开始时，Redis会创建一个新的哈希表（称为哈希表2），而旧的哈希表（称为哈希表1）仍然保留。这时，Redis同时维护这两个哈希表。</span></p>
  <p data-lake-id="u1fb77610" id="u1fb77610"><br></p>
  <p data-lake-id="u006fadb4" id="u006fadb4"><span data-lake-id="ub7ceedfd" id="ub7ceedfd">当执行查询操作时，Redis首先会在哈希表1中查找键。如果在哈希表1中没找到，Redis会接着在哈希表2中查找。这确保了即使在Rehash过程中，所有的键都是可查询的。</span></p>
  <p data-lake-id="u105c366e" id="u105c366e"><br></p>
  <p data-lake-id="u0b51d20b" id="u0b51d20b"><span data-lake-id="u7f02f6c6" id="u7f02f6c6">当哈希表1中的所有数据都迁移到哈希表2后，Rehash操作完成。此时，哈希表1会被释放，哈希表2成为当前使用的哈希表。 查询就直接查询哈希表2即可</span></p>
 </body>
</html>